﻿using System;
using System.Collections.Generic;
using System.Linq;

using iTool.Cloud.Center.ServiceProvider;
using iTool.Clustering.Center;
using iTool.Common;

using Microsoft.Extensions.Logging;

using Orleans.Runtime;

namespace iTool.Cloud.Center.Logger
{
    internal class iCenterLogger : ILogger
    {

        private readonly string typeName;
        //private readonly Func<iCenterLoggerConfiguration> _getCurrentConfig;
        private IClusterLoggerService? clusterLoggerService;

        private readonly string ProviderName;
        private readonly LogLevel MinLogLevel;
        private readonly bool IsFilter;

        public iCenterLogger(string name, Func<iCenterLoggerConfiguration> getCurrentConfig)
        {
            this.typeName = name;
            //this._getCurrentConfig = getCurrentConfig;
            this.ProviderName = getCurrentConfig().ProviderName;
            this.MinLogLevel = getCurrentConfig().MinLogLevel;
            this.IsFilter = getCurrentConfig().FilterTypeNames?.Contains(this.typeName) == true;

            iCenterClusterClient clusterClient = iBox.GetService<iCenterClusterClient>("IClusterService");
            if (iCenter.iGrainFactory != null || clusterClient != null)
            {
                if (iCenter.iGrainFactory == null)
                {
                    this.clusterLoggerService = clusterClient.GetGrain<IClusterLoggerService>(this.ProviderName);
                }
                else
                {
                    this.clusterLoggerService = iCenter.iGrainFactory.GetGrain<IClusterLoggerService>(this.ProviderName);
                }
            }
        }

        public IDisposable? BeginScope<TState>(TState state) where TState : notnull => default!;

        public bool IsEnabled(LogLevel logLevel) => logLevel >= this.MinLogLevel && !this.IsFilter;

        public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
        {
            if (!IsEnabled(logLevel))
            {
                return;
            }

            if (this.clusterLoggerService == null) 
            {
                if (iCenter.iGrainFactory != null)
                {
                    this.clusterLoggerService = iCenter.iGrainFactory.GetGrain<IClusterLoggerService>(this.ProviderName);
                }
                else
                {
                    iCenterClusterClient clusterClient = iBox.GetService<iCenterClusterClient>("IClusterService");
                    if (clusterClient != null)
                    {
                        this.clusterLoggerService = clusterClient.GetGrain<IClusterLoggerService>(this.ProviderName);
                    }
                }

                if (this.clusterLoggerService == null)
                {
                    switch (logLevel)
                    {
                        case LogLevel.Trace:
                            break;
                        case LogLevel.Debug:
                            Console.ForegroundColor = ConsoleColor.DarkYellow;
                            break;
                        case LogLevel.Information:
                            Console.ForegroundColor = ConsoleColor.DarkGreen;
                            break;
                        case LogLevel.Warning:
                            Console.WriteLine("\n");
                            Console.ForegroundColor = ConsoleColor.DarkMagenta;
                            break;
                        case LogLevel.Error:
                            Console.WriteLine("\n");
                            Console.ForegroundColor = ConsoleColor.Red;
                            break;
                        case LogLevel.Critical:
                            break;
                        case LogLevel.None:
                            break;
                    }
                    Console.WriteLine(string.Format("{0} ({1})\n{2}", logLevel, this.typeName, formatter(state, exception)));
                    Console.ForegroundColor = ConsoleColor.White;
                    return;
                }
            }

            switch (logLevel)
            {
                case LogLevel.Trace:
                    this.clusterLoggerService?.LogTraceAsync(this.typeName, formatter(state, exception), eventId.Id);
                    break;
                case LogLevel.Debug:
                    this.clusterLoggerService?.LogDebugAsync(this.typeName, formatter(state, exception), eventId.Id);
                    break;
                case LogLevel.Information:
                    this.clusterLoggerService?.LogInformationAsync(this.typeName, formatter(state, exception), eventId.Id);
                    break;
                case LogLevel.Warning:
                    this.clusterLoggerService?.LogWarningAsync(this.typeName, formatter(state, exception), eventId.Id);
                    break;
                case LogLevel.Error:
                    this.clusterLoggerService?.LogErrorAsync(this.typeName, formatter(state, exception), eventId.Id);
                    break;
                case LogLevel.Critical:
                    this.clusterLoggerService?.LogCriticalAsync(this.typeName, formatter(state, exception), eventId.Id);
                    break;
                case LogLevel.None:
                    this.clusterLoggerService?.LogNoneAsync(this.typeName, formatter(state, exception), eventId.Id);
                    break;
            }


            //iCenterLoggerConfiguration config = _getCurrentConfig();
            //if (config.EventId == 0 || config.EventId == eventId.Id)
            //{
            //    ConsoleColor originalColor = Console.ForegroundColor;

            //    Console.ForegroundColor = config.LogLevelToColorMap[logLevel];
            //    Console.WriteLine($"[{eventId.Id,2}: {logLevel,-12}]");

            //    Console.ForegroundColor = originalColor;
            //    Console.Write($"     {_name} - ");

            //    Console.ForegroundColor = config.LogLevelToColorMap[logLevel];
            //    Console.Write($"{formatter(state, exception)}");

            //    Console.ForegroundColor = originalColor;
            //    Console.WriteLine();
            //}
        }
    }
}